Crate i18n_pattern

source ·
Expand description

Parsing of string tokens into an Abstract Syntax Tree (AST), checking the grammar of patterns is valid. The parser only does the syntactic analysis of the supplied Token vector.

The formatter takes the Abstract Syntax Tree (AST) that was generated by the parser and constructs a string template for values to be substituted into. The formatter also does the semantic analysis of the grammar. Once a string template has been constructed, it can be used multiple times by simply supplying new placeholder values when executing the format() method. Depending on the placeholder type of the pattern, a suitable selection of the available data types can be used, these include the basic String, integers, unsigned integers and floats. In addition to these special ICU4X types are supported such as FixedDecimal, Date, Time and DateTime structs.

See pattern strings.asciidoc in docs of pattern for the pattern formatting specification.

Examples

use i18n_icu::IcuDataProvider;
use i18n_lexer::{Token, TokenType, tokenise};
use i18n_pattern::{
    parse, NodeType, Formatter, FormatterError, PlaceholderValue, CommandRegistry, english_a_or_an
};
use icu_testdata::buffer;
use icu_provider::serde::AsDeserializingBufferProvider;
use icu_locid::Locale;
use std::collections::HashMap;
use std::rc::Rc;
use std::error::Error;
 
fn pattern_plural() -> Result<(), Box<dyn Error>> {
    let buffer_provider = buffer();
    let data_provider = buffer_provider.as_deserializing();
    let icu_data_provider = Rc::new( IcuDataProvider::try_new( &data_provider )? );
    let tokens = tokenise(
        "There {dogs_number plural one#one_dog other#dogs} in the park.#{dogs are # dogs}{one_dog is 1 dog}",
        &vec![ '{', '}', '`', '#' ],
        &icu_data_provider,
    );
    let tree = parse( tokens.0 )?;
    let locale: Rc<Locale> = Rc::new( "en-ZA".parse()? );
    let language_tag = Rc::new( locale.to_string() );
    let command_registry = Rc::new( CommandRegistry::new() );
    let mut formatter = Formatter::try_new(
        &icu_data_provider, &language_tag, &locale, &tree, &command_registry
    )?;
    let mut values = HashMap::<String, PlaceholderValue>::new();
    values.insert(
        "dogs_number".to_string(),
        PlaceholderValue::Unsigned( 3 )
    );
    let result = formatter.format( &values )?;
    assert_eq!( result.as_str(), "There are 3 dogs in the park.", "Strings must be the same." );
    Ok( () )
}
 
fn command_delayed() -> Result<(), Box<dyn Error>> {
    let buffer_provider = buffer();
    let data_provider = buffer_provider.as_deserializing();
    let icu_data_provider =
        Rc::new( IcuDataProvider::try_new( &data_provider )? );
    let tokens = tokenise(
        "At night {#english_a_or_an# hunter} {hunter} stalked {#english_a_or_an # prey} {prey}.",
        &vec![ '{', '}', '`', '#' ],
        &icu_data_provider,
    );
    let tree = parse( tokens.0 )?;
    let locale: Rc<Locale> = Rc::new( "en-ZA".parse()? );
    let language_tag = Rc::new( locale.to_string() );
    let command_registry = Rc::new( CommandRegistry::new() );
    command_registry.insert( "english_a_or_an", english_a_or_an )?;
    let mut formatter =
        Formatter::try_new( &icu_data_provider, &language_tag, &locale, &tree, &command_registry )?;
    let mut values = HashMap::<String, PlaceholderValue>::new();
    values.insert(
        "hunter".to_string(),
        PlaceholderValue::String( "owl".to_string() )
    );
    values.insert(
        "prey".to_string(),
        PlaceholderValue::String( "mouse".to_string() )
    );
    let result = formatter.format( &values )?;
    assert_eq!(
        result.as_str(),
        "At night an owl stalked a mouse.",
        "Strings must be the same."
    );
    Ok( () )
}

Re-exports

Modules